/*
需求：
[root@master input]# ls
101it.seg.cln.txt  174it.seg.cln.txt  252it.seg.cln.txt  593it.seg.cln.txt  666it.seg.cln.txt  740it.seg.cln.txt  814it.seg.cln.txt
102it.seg.cln.txt  175it.seg.cln.txt  253it.seg.cln.txt  594it.seg.cln.txt  667it.seg.cln.txt  741it.seg.cln.txt  815it.seg.cln.txt
[root@master input]# ls | wc -l
508

/data/input 这个目录总共有508篇文章，现在想将每篇文章合并成一行，然后写入一个文件，并给每一行添加一个行号。这个文件就有508行。
508篇文章变成了一个文件，有508行，而且每一行对应以前的每一篇文章

现在看一篇文章的内容(部分内容)
[root@master input]# cat 174it.seg.cln.txt
雷锋 网 ： 百度 缺 的 不是 狼 性 ， 而是 鲁滨逊 搜狐 
 撇开 商业 模式 不 谈 ， 百度 是 个 好 公司 ， 不管 从 治理 上 还是 从 文化 上 ， 都 是 中国 需要 的 那 类 公司 。 李彦宏 是 个 有些 西化 的 人 ， 却 还 很 保留 着 东方人 的 内敛 和 含蓄 ， 既 不 像 马云 那样 喜欢 当 偶像 ， 也 不 像 小马哥 那样 事必躬亲 ， 百度 在 上下班 时间 和 员工 着装 方面 没 那么 死板 ， 甚至 还 能 带 宠物 去 单位 ， 这 都 渗透 了 很 多 他 的 个人 色彩 。 
 百度 是 个 去 中心化 的 公司 ， 老板 不会 给 下属 施加 太 多 主观 压力 ， 员工 们 也 不会 整天 战战兢兢 ， 唯 恐 出错 惹 上司 不 高兴 ， 这 与 很 多 的 中国 公司 不同 ， 是 百度 的 优点 。 我 曾 说 过 ， 就 企业 文化 而 言 ， 我 认为 百度 好 于 阿里巴巴 ， 好 于 苹果 。 当然 ， 过去 几 年 的 高速 成长 ， 也 给 百度 带来 了 巨大 财富 ， 从 老板 角度 来 说 ， 也 愿意 给 员工 创造 更 好 的 条件 ， 给 出 更 好 的 待遇 ， 让 员工 过 上 体面 的 生活 。 这些 ， 都 是 百度 的 好处 。 
 不过 百度 也 有 自己 的 问题 ， 那 就是 太 会 权衡利弊 ， 趋利避害 了 ， 此外 还 缺乏 一些 进取心 。 百度 在 业务 拓展 上 ， 始终 是 小心翼翼 的 ， 百科 、 贴吧 、 知道 、 视频 、 文库 ， 这些 业务 别 管 最终 是否 出彩 ， 最 起码 也 对 其 搜索 业务 有 所 助益 ， 谈 不 上 革命性 ， 却 一定 有 功利性 。 今年 三季 报 百度 营 收 亿 美元 ， 增长 ， 这 已经 是 连续 七 个 季度 高 增长 了 。 季 报 出来 后 ， 百度 股价 应声 下跌 。 机构 和 分析师 分化 成 两 个 阵营 ， 一派 强力 看 空 至 美元 左右 ， 一派 看 多 至 美元 ， 两 派 中 各自 不乏 重量级 选手 。 有 人 会 把 这 理解 为 奇虎 的 竞争 所 致 ， 但 分析师 会议 上 根本 连 提 都 没 提 奇虎 的 名字 ， 大家 都 对 百度 的 移动 营 收 穷追 不 放 。 华尔街 放空 百度 股票 的 最 主要 原因 ， 就是 其 缓慢 的 移动 业务 拓展 。

 最终的结果：
 [root@master input]# hadoop fs -text hdfs://master:9000/spark_mergefile_output_last/part-00000 | head -3
1001	光棍节 大 脱光 准 男女 朋友 情侣机 对对碰 搜狐 数码   三星   参考价格 元   电池容量   三星 是 一 款 备受 关注 的 高端 手机 其 搭载 了 一 颗 四核 高性能 处理器 而且 用户 体验 也 更加 出色 拥有 多 项 创新性 的 新技术 在 各 方面 的 表现 它 都 得 非常 出色 甚至 会 超越 的 表现  光棍节 大 脱光 准 男女 朋友 情侣机 对对碰    图 为 三星 手机   图 为 三星 手机   三星 的 设计 灵感 源于 水 和 鹅卵石 外观 较为 圆润 正面 搭载 了 英 像素 的 高清 屏幕 显示 效果 相当 出众 正面 还 拥有 一 颗 万 像素 的 前置 摄像头 用于 自拍 以及 视频 通话  光棍节 大 脱光 准 男女 朋友 情侣机 对对碰    图 为 三星 手机   图 为 三星 手机   三星 采用 了 系统 以及 最新 的 搭载 了 四 核心 处理器 主频 运行 内存 手机 的 主 摄像头 为 万 像素 可以 零 延迟 快速 对 焦 真正 做到 所见 即 所 拍 此外 三星 添加 了 语音 识别 等 众多 创新性 的 人 机 交互 技术 在 用户 体验 上 有着 跨越式 的 提升   产品名称 三星 行货   销售 价格 元  点评 赢 智能 手机 大奖  满 评 美女 撞 僵尸  安卓 精品 松饼 骑士  江南 美女 的 性感 诱惑  精彩 推荐  原创 汉化 拍照 神器 让 你 的 变 单反  精品 休闲 游戏 续 作 宝石迷阵  本周 热门 游戏 更新 汇总 总 有 你 喜欢 的  爆料 传言 苹果 已经 开始 准备 生产   手机 贴膜 知 多少 详解 哪 种 类型 最 适合 你  教 你 解决 手机 内存 空间 不足 的 问题  近期 最 热门 的 五十 多 款 游戏 玩 爆 你 的 手机   葵花宝典 之 手机 设置 宝典  上 一 页  下 一 页  文本 导航  第 页 黑白配  第 页 摩托罗拉 摩托罗拉  第 页 行货  第 页 三星 蓝白 配  第 页 索尼 索尼  第 页 联想 乐 联想 乐  分享 

1002	仅 售 元 本周 降价 智能 手机 一览 搜狐 数码   三星 行货 降幅 元   参考价格 元   三星 是 一 款 高端 定位 的 出色 产品 它 的 设计 出色 拥有 两 块 英寸 的 屏幕 并 搭载 了 双核 的 处理器 在 性能 方面 无需 置疑 而且 其 可以 支持 双模 双待 功能 实用性 极 强  图 为 三星 手机   图 为 三星 手机   三星 的 外观 设计 和 区别 不大 同样 是 采用 日韩 风范 儿 的 大 翻盖 造型 同时 还 加入 了 内外 双屏 的 设计 整体 看 上去 大气 十足 尊荣 不凡 并且 该 机 的 两 块 屏幕 均 是 英寸 材质 的 触控 屏幕 画面显示 效果 尤 为 细腻 还 支持 多 点 触控 操作  图 为 三星 手机   图 为 三星 手机   三星 的 机身 上 内置 一 颗 万 像素 摄像头 还 配备 了 一 颗 主频 的 双核 芯 处理器 及 运行 内存 则 为 此外 还 支持 双卡 双模 功能   产品名称 三星 行货   销售 价格 元  点评 赢 智能 手机 大奖  满 评 美女 撞 僵尸  安卓 精品 松饼 骑士  江南 美女 的 性感 诱惑  精彩 推荐  原创 汉化 拍照 神器 让 你 的 变 单反  精品 休闲 游戏 续 作 宝石迷阵  本周 热门 游戏 更新 汇总 总 有 你 喜欢 的  爆料 传言 苹果 已经 开始 准备 生产   手机 贴膜 知 多少 详解 哪 种 类型 最 适合 你  教 你 解决 手机 内存 空间 不足 的 问题  近期 最 热门 的 五十 多 款 游戏 玩 爆 你 的 手机   葵花宝典 之 手机 设置 宝典  上 一 页  文本 导航  第 页 诺基亚  第 页 三星  第 页 诺基亚  第 页 三星  第 页  第 页 三星  第 页 摩托罗拉  第 页 三星  分享 

[root@master input]# hadoop fs -text hdfs://master:9000/spark_mergefile_output_last/part-00000 | tail -5
1507	恋 上 那 片 海 携 宾得 越南 海岛 行 搜狐 数码   美 奈 赏 美景   还 没有 在 富国岛 待 够 一 行人 又 要 向 越南 另 一个 岛屿 出发 美 奈 越南语 作 是 一个 渔村 小镇 位置 在 胡志明 市 东北 约 的 半岛 上 离 约 但是 旅游 意义 上 的 则 是 指 从 出发 约 开始 并且 经过 镇 继续 向 北 方向 延伸 总长 约 的 绵长 海滩 椰风 海浪 水 清 沙 幼  美 奈 赏 美景  美 奈 赏 美景   与 富国岛 不同 的 是 美 奈 岛 上人 并 不算 很 多 怎么 说 人 以前 也 只是 个 淳朴 的 小 渔村 么 人 不 多 风景 倒是 很 好 各种 不同 风格 的 旅游 度假村 就 在 海滩 边上 推 窗 就是 海 美 哉 美 哉  美 奈 赏 美景  美 奈 赏 美景  美 奈 赏 美景  恋 上 那 片 海 携 宾得 越南 海岛 行  美 奈 赏 美景   前 两 天 在 富国岛 的 疯 玩 让 我 的 身子 有些 吃 不消 美 奈 又 是 那么 美 我 就 不 跟着 他们 去 疯 了 就 附近 走 走 拍拍 宾得 也 就 挂 在 包 上 随便 他 晃荡 反正 三防 相机 就是 耐 摔 不 像 其他 相机 那么 娇气  美 奈 赏 美景  美 奈 赏 美景  美 奈 赏 美景  美 奈 赏 美景   别 看 美 奈 只是 个 小 渔村 真真 是 让 人 流连 忘返 美景 有 好玩 的 也 有 这 不 我 那 帮 不 安分 的 兄弟 姐妹 们 又 拉 着 我 去 玩 什么 越野 赛车 也 是 这 是 来 度假 来 玩 不 能 光 发呆 了 说 到 美 奈 人 都会 说 美 奈 一边 是 沙滩 一边 是 沙漠 我们 小团体 的 越野 赛车赛 就 在 美 奈 的 红 沙漠 上 飞驰 起来  美 奈 的 红 沙漠  恋 上 那 片 海 携 宾得 越南 海岛 行  美 奈 的 红 沙漠   不 能 不 说 此次 越南 海岛 之 旅 给 我 来 很 多 感触 也 有 很 多 惊喜 更 让 我 感叹 的 是 我 手 中 的 这 款 酷似 法拉利 的 宾得 不仅 三防 性能 极 佳 上天 入 水都 没 问题 就算 是 普通 环境 中 万 像素 的 画质 也 让 我 心满意足  宾得 恋 上 这 片 海  宾得 恋 上 这 片 海  上 一 页  文本 导航  第 页 宾得 越南 海岛 行  第 页 富国岛 浮潜  第 页 美 奈 赏 美景  分享 


1508	与 苹果 握手言和 达成 十年 授权 搜狐   黄远   苹果 和 宏达 电子 的 专利 纠纷 终于 落下帷幕   日前 两 家 公司 发表 联合声明 称 和 苹果 达成 全球性 和解 协议 撤销 当前 所有 针对 对方 的 诉讼 并 签署 为期 年 的 许可 协议 许可 协议 不仅 涉及 双方 现有 专利 也 包含 未来 获得 的 专利   周永明 与 苹果 蒂姆 库克 均 对 和解 协议 表示 满意 但 双方 的 措辞 存在 细微 差别 周永明 称 会 关注 创新 而 非诉讼 而 库克 则 表示 苹果 会 继续 专注 于 创新   与 苹果 的 专利 纷争 由来已久 自 年月 以来 苹果 和 便 因 智能 手机 中 的 一些 专利 技术 发生 纠纷 年月日 苹果 首先 向 美国 国际 贸易 委员会 下 称 和 美国 区 法院 起诉 指控 其 侵犯 项 专利 直到 去年 月 才 做出 了 有利 于 苹果 的 裁决 认定 侵犯 了 苹果 的 号 专利 并 从 今年 月 日 起 对 涉及 该 项 专利 的 多 款 智能 手机 实施 正式 进口 禁令   在 诉讼 前 曾 是 美国 最大 的 智能 手机 制造商 一度 占据 着 的 市场 份额 但 遭受 专利 诉讼 打击 后 在 美国 的 销量 一落千丈 今年 第三 季度 手机 在 美国 的 占有率 仅 有   与此同时 也 针对 苹果 提出 反诉 称 苹果 侵犯 其 无线 技术 专利 提出 诉讼 的 两 项 专利 均 与 技术 有关 如果 胜诉 可 寻求 在 美国 禁 售 新 自 月 日 以来 两 家 公司 曾 就此 举行 多 次 和解 谈判 未 果   分析 人士 认为 苹果 和 两 家 公司 都 被 专利 纠纷 搞 得 焦头烂额 和解 之后 更 利于 专注 创新 下 一步 的 工作 重心 是 夺 回 市场 但 苹果 还 面临 与 三星 摩托罗拉 等 多 家 设备 厂商 在 全球 的 纷争   不久前 在 苹果 与 三星 的 英国 专利 诉讼 中 以 苹果 的 完败 宣告 结束 本月 初 起 苹果 英国 官网 开始 刊登 对 三星 的 道歉 声明  分享 

*/

import org.apache.spark._
import SparkContext._
import java.io.File

object mergeFile {
    def main(args: Array[String]) {
        val conf = new SparkConf().setAppName("mergeFile")

        val sc = new SparkContext(conf)
        //val output = "hdfs://master:9000/spark_mergefile_output"
        val output = args(1).toString
        import scala.util.matching.Regex
        // 匹配非中文，文中有很多标点符号，将其过滤掉。
        // pattern.replaceAllIn(x," ") 把那些标点符号换成空格
        // "[\u4e00-\u9fa5]+" 匹配中文，前面加一个^ 表示匹配中文以外的字符，刚好这些文章中除了中文就是标点符号。
        val pattern = "[^\u4e00-\u9fa5]+"r
        // 行号
        var index = 1001
        for(fd <- subDir(new File(args(0).toString))) {
            val input = sc.textFile(fd.toString).map(x => pattern.replaceAllIn(x," ")).collect()
            // n 表示将n行合并成1行
            val n = input.length
            
            val numSlices = input.length / n
            val output_index = output + "/" + index.toString
            // x 赋值这段没有看懂，这是在网上抄别人的代码。
            val x = sc.parallelize(input, numSlices).zipWithIndex().aggregate(List.empty[List[String]])(seqOp = 
                (result, lineWithIndex) => {
                    lineWithIndex match {
                    case (line, index) =>
                    if (index % n == 0) List(line) :: result else (line :: result.head) :: result.tail
                    }
                }, combOp = (x, y) => x ::: y).map(_.reverse mkString " ")
            sc.parallelize(x).map(x=> (index.toString + "\t" + x)).saveAsTextFile(output_index)
            index += 1
        }
        val mergeDir = output + "/" + "*"
        val outputLast = output + "_" + "last"
        /*
        wholeTextFiles 这个函数将目录中的文件都读取到一个RDD中，返回一个元组(filename,filecontext)。
        filename:文件名，hdfs上的绝对路径
        filecontext: 文件的内容
        map(x => x._2) 读取元组中的第二个元素，注意索引是从1开始
        */
        val lineContext = sc.wholeTextFiles(mergeDir)
        // repartition(n) 将原RDD重新划分区，划分为n个区
        lineContext.map(x => x._2).repartition(1).saveAsTextFile(outputLast)
    }
    // 这个函数的作用是将目录下所有的文件都返回，返回的是绝对路径
    /*
    这个函数返回的结果：
    /data/input/101it.seg.cln.txt
    /data/input/102it.seg.cln.txt
    /data/input/103it.seg.cln.txt
    /data/input/104it.seg.cln.txt
    ...........

    对于这个函数还要特别说明的是每个work节点都需要有/data/input 这个目录，总共508个文件，否则就会报空指针。这个函数只能读取本地的文件
    val input = sc.textFile(fd.toString).map(x => pattern.replaceAllIn(x," ")).collect()
    这样是从hdfs上创建RDD，所以hdfs上也应该有/data/input 这个目录，总共508个文件
    所以 hadoop fs -put /data/input /data/input
    */
    def subDir(dir :File) :Iterator[File] = {
        val dirs = dir.listFiles().filter(_.isDirectory())
        val files = dir.listFiles().filter(_.isFile())
        files.toIterator ++ dirs.toIterator
    }
}

/*
sc.parallelize(x).map(x=> (index.toString + "\t" + x)).saveAsTextFile(output_index) 对这句做下解释 
$output 这个目录下会产生多个子目录1001 -- 1508
查看一个目录，其他的目录相同
[root@master input]# hadoop fs -ls hdfs://master:9000/spark_mergefile_output/1001
Found 3 items
-rw-r--r--   3 root supergroup          0 2018-04-25 16:49 hdfs://master:9000/spark_mergefile_output/1001/_SUCCESS
-rw-r--r--   3 root supergroup          0 2018-04-25 16:49 hdfs://master:9000/spark_mergefile_output/1001/part-00000
-rw-r--r--   3 root supergroup       2000 2018-04-25 16:49 hdfs://master:9000/spark_mergefile_output/1001/part-00001
只有part-00001 这个文件有内容，这个文件只有1行，行号是1001，和目录名一致
[root@master input]# hadoop fs -text hdfs://master:9000/spark_mergefile_output/1001/part-00001
1001	光棍节 大 脱光 准 男女 朋友 情侣机 对对碰 搜狐 数码   三星   参考价格 元   电池容量   三星 是 一 款 备受 关注 的 高端 手机 其 搭载 了 一 颗 四核 高性能 处理器 而且 用户 体验 也 更加 出色 拥有 多 项 创新性 的 新技术 在 各 方面 的 表现 它 都 得 非常 出色 甚至 会 超越 的 表现  光棍节 大 脱光 准 男女 朋友 情侣机 对对碰    图 为 三星 手机   图 为 三星 手机   三星 的 设计 灵感 源于 水 和 鹅卵石 外观 较为 圆润 正面 搭载 了 英 像素 的 高清 屏幕 显示 效果 相当 出众 正面 还 拥有 一 颗 万 像素 的 前置 摄像头 用于 自拍 以及 视频 通话  光棍节 大 脱光 准 男女 朋友 情侣机 对对碰    图 为 三星 手机   图 为 三星 手机   三星 采用 了 系统 以及 最新 的 搭载 了 四 核心 处理器 主频 运行 内存 手机 的 主 摄像头 为 万 像素 可以 零 延迟 快速 对 焦 真正 做到 所见 即 所 拍 此外 三星 添加 了 语音 识别 等 众多 创新性 的 人 机 交互 技术 在 用户 体验 上 有着 跨越式 的 提升   产品名称 三星 行货   销售 价格 元  点评 赢 智能 手机 大奖  满 评 美女 撞 僵尸  安卓 精品 松饼 骑士  江南 美女 的 性感 诱惑  精彩 推荐  原创 汉化 拍照 神器 让 你 的 变 单反  精品 休闲 游戏 续 作 宝石迷阵  本周 热门 游戏 更新 汇总 总 有 你 喜欢 的  爆料 传言 苹果 已经 开始 准备 生产   手机 贴膜 知 多少 详解 哪 种 类型 最 适合 你  教 你 解决 手机 内存 空间 不足 的 问题  近期 最 热门 的 五十 多 款 游戏 玩 爆 你 的 手机   葵花宝典 之 手机 设置 宝典  上 一 页  下 一 页  文本 导航  第 页 黑白配  第 页 摩托罗拉 摩托罗拉  第 页 行货  第 页 三星 蓝白 配  第 页 索尼 索尼  第 页 联想 乐 联想 乐  分享

这是一个中间结果。本来想一次性把508篇文章，中每篇文章合并成一行，然后写入一个文件中，并给每行指定一个行号，可是RDD 无法这么操作
val rdd = sc.textFile("/tmp/zerofile") /tmp/zerofile 空文件
val rdd1 = sc.textFile("/data/input/985it.seg.cln.txt")
val rdd = rdd.union(rdd1) RDD 不支持这样合并
val rdd2 = rdd.union(rdd1)  这样是可以的
这里应该可以优化的，每一个文件创建一个RDD，将这些RDD 不写入文件而是缓存起来，然后将所有的RDD合并后在写入文件中
      
*/

/*
这里给出coalesce 和 repartition 这两个函数的区别。摘自网上的，没有去验证过，不知道是否正确，仅供参考
coalesce

def coalesce(numPartitions:Int，shuffle:Boolean=false):RDD[T] 
该函数用于将RDD进行重分区，使用HashPartitioner。 
第一个参数为重分区的数目，第二个为是否进行shuffle，默认为false。

repartition

def repartition(numPartitions: Int): RDD[T] 
该函数其实就是coalesce函数第二个参数为true的实现。

使用注意

他们两个都是RDD的分区进行重新划分，repartition只是coalesce接口中shuffle为true的简易实现，（假设RDD有N个分区，需要重新划分成M个分区） 
1）N < M。一般情况下N个分区有数据分布不均匀的状况，利用HashPartitioner函数将数据重新分区为M个，这时需要将shuffle设置为true。 
2）如果N > M并且N和M相差不多，(假如N是1000，M是100)那么就可以将N个分区中的若干个分区合并成一个新的分区，最终合并为M个分区，这时可以将shuff设置为false，在shuffl为false的情况下，如果M>N时，coalesce为无效的，不进行shuffle过程，父RDD和子RDD之间是窄依赖关系。 
3）如果N > M并且两者相差悬殊，这时如果将shuffle设置为false，父子RDD是窄依赖关系，他们同处在一个stage中，就可能造成Spark程序的并行度不够，从而影响性能，如果在M为1的时候，为了使coalesce之前的操作有更好的并行度，可以讲shuffle设置为true。
*/
/*
向集群提交spark任务
#!/bin/bash
/data/hadoop/bin/hadoop fs -rm -r -skipTrash /spark_mergefile_output
/data/hadoop/bin/hadoop fs -rm -r -skipTrash /spark_mergefile_output_last
cd /data/project/spark/spark_workstation
/data/sbt/bin/sbt compile && /data/sbt/bin/sbt package && \
/data/spark/bin/spark-submit --master yarn-cluster \
	--num-executors 2 \
	--executor-memory '1024m' \
	--executor-cores 1 \
	--class spark.example.mergeFile ./target/scala-2.11/mergefile_2.11-2.2.1.jar \
    /data/input \
    hdfs://master:9000/spark_mergefile_output
*/